package players;

import java.util.ArrayList;
import java.util.Random;

import staticClasses.Action;
import staticClasses.Global;
import staticClasses.Square;

public class EASY extends Behavior{
	/**
	 * The player that instantiates the classes, and so, the one being watched
	 */
	Player player;
	
	/**
	 * Constructor for a player with an easy behavior
	 * @param p the player being watched
	 */
	public EASY(Player p){
		this.player = p;
	}
	
	
	public Action whatToDo(){
		//General behavior of a player, refresh every second.
		
		Random r = new Random();
		
		Player opponent = Global.nearestOpponent(player);
		ArrayList<int[]> oppGoalLine=null;
		
		if(player.isInLocalTeam){
			oppGoalLine = Global.visitorTeam_goalLine;
		}else{
			oppGoalLine = Global.localTeam_goalLine;
		}
		
		if(Global.getBallOwner()!=null && Global.getBallOwner().equals(player)){
			
			if(Global.shortestLine(player.getPosition()[0],player.getPosition()[1], oppGoalLine).size()<(100+r.nextInt(150))){
				//if the goalLine is between 0 and 10 meters, the player shoots.
				//if the goalLine is between 10 and 25 meters, the player shoots.
				return Action.SHOOT;
			}
			
			if(Global.bresenham(opponent.getPosition()[0], opponent.getPosition()[1],
					player.getPosition()[0], player.getPosition()[1]).size()<50){
				
				//if an opponent is closer than 5 meters
				if(r.nextInt(3)==0){
					//once every 3 times, continue attacking
					return Action.ATTACK;
				}else{
					//twice every 3 times, Pass
					return Action.PASS;
				}
			}
			
			if(r.nextInt(2)==0){
				return Action.ATTACK;
			}
			
			return Action.PASS;
		}
		else{
			if(Global.getBallOwner()!=null && Global.getBallOwner().getClass().getCanonicalName().equals(
					(new GoalKeeper(new Square(0, 0))).getClass().getCanonicalName())
					){
				return Action.DEFEND;
			}
			else if(Global.getBallOwner()!=null && Global.getBallOwner().isInLocalTeam == player.isInLocalTeam){
				return Action.ATTACK;
			}
			else if(Global.getBallOwner()!=null && Global.getBallOwner().isInLocalTeam != player.isInLocalTeam){
				if(Global.bresenham(Global.ball.getPosition()[0], Global.ball.getPosition()[1],
						player.getPosition()[0], player.getPosition()[1]).size()<150){
					return Action.RUN_TO_THE_BALL;
				}
				return Action.DEFEND;
			}
			else{
				if(Global.bresenham(Global.ball.getPosition()[0], Global.ball.getPosition()[1],
				   player.getPosition()[0], player.getPosition()[1]).size()<150
				   && (player.ballState==0 || player.ballState==2)){
					return Action.RUN_TO_THE_BALL;
				}
				else if(Global.bresenham(Global.ball.getPosition()[0], Global.ball.getPosition()[1],
						   player.getPosition()[0], player.getPosition()[1]).size()<150
						   && player.ballState==1){
					return Action.ATTACK;
				}
				else{
					return Action.DEFEND;
				}
			}
		}
	}
	
	@Override
	public void execAction(){
		
		switch(player.nextAction){
		case SHOOT:
			if(Global.getBallOwner().equals(player)){
				player.ballState=0;
				Global.setBallOwner(null);
				int[] target = new int[2];
				if(player.isInLocalTeam){
					target[0] = Global.MapSize[0]-1;
					double temp = ((double)player.accuracy)+127.0;
					temp = 256.0/temp;
					temp *= (((double)((new Random()).nextInt(144)))-72.0);
					target[1] = (Global.MapSize[1]-1)/2+(int)temp;
				}else{
					target[0] = 0;
					double temp = ((double)player.accuracy)+127.0;
					temp = 256.0/temp;
					temp = (((double)((new Random()).nextInt(144)))-72.0);
					target[1] = (Global.MapSize[1]-1)/2+(int)temp;
				}
				Global.ball.targeted_case[0] = target[0];
				Global.ball.targeted_case[1] = target[1];
				Global.ball.velocity = player.power+(((new Random()).nextInt(100)-50)*player.power)/100;
				Global.ball.traveledDist = 0;
				player.nextAction=Action.ATTACK;
				player.refreshAction=19;
				System.out.println(player.isInLocalTeam+"\t"+player+"- Je shoot!");
			}
			break;
			
		case PASS:
			Global.setBallOwner(null);
			player.ballState = 1;
			Player teammate = Global.nearestTeamMate(player);
			teammate.ballState=2;
			Global.ball.targeted_case[0] = teammate.getPosition()[0];
			Global.ball.targeted_case[1] = teammate.getPosition()[1];
			Global.ball.velocity = (player.power+(((new Random()).nextInt(100)-50)*player.power)/100)/2;
			Global.ball.traveledDist = 0;
			player.refreshAction=19;
			System.out.println(teammate.isInLocalTeam+"\t"+teammate+"- j'ai été pris pour cible d'une passe");
			break;
			
		case ATTACK:
			ArrayList<int[]> oppGoalLine=null;
			Random r = new Random();
			
			if(player.isInLocalTeam){
				oppGoalLine = Global.visitorTeam_goalLine;
			}else{
				oppGoalLine = Global.localTeam_goalLine;
			}
			
			if(Global.shortestLine(player.getPosition()[0],player.getPosition()[1], oppGoalLine).size()<(100+r.nextInt(150))
					&& Global.getBallOwner()!=null && Global.getBallOwner().equals(player)){
				player.nextAction=Action.SHOOT;
			}
			else if(player.ballState==2){
				player.refreshAction=19;
				player.nextAction=Action.RUN_TO_THE_BALL;
			}
			else{
				double x_mov = (double)player.speed;
				x_mov = x_mov/127.0+1;//ratio speed of the player from 1 (with 0 speed) to 2 (with 255 speed)
				x_mov *= 4.0;//base speed is 4m/s
				x_mov /= 20;//speed per tick, a tick is 50ms
				x_mov*=10;//multiply by 10 cause there are 10 case per meter
				int[] pos = player.getPosition();
				
				if(player.getPosition()[0]>200 && player.getPosition()[0]<700){
					int playerSide=1;//if the player is in local team, he moves in the direction of increasing x axis
					if(!player.isInLocalTeam){
						playerSide=-1;//else, the player is in visitor team, he moves in the direction of decreasing x axis
					}
					player.setPosition(pos[0]+playerSide*((int)Math.round(x_mov)), pos[1]);
				}
				else{
					int[] to = {Global.visitorTeam_6meter.x,Global.visitorTeam_6meter.y};
					if(!player.isInLocalTeam){
						to[0] = Global.localTeam_6meter.x;
						to[1] = Global.localTeam_6meter.y;
					}
					ArrayList<int[]> path = Global.bresenham(pos[0], pos[1], to[0], to[1]);
					if(path.size()>Math.round(x_mov)){
						player.setPosition(path.get((int)Math.round(x_mov))[0], path.get((int)Math.round(x_mov))[1]);
					}
				}
			}
			break;
			
		case DEFEND:
			if(true){
				double x_mov = (double)player.speed;
				x_mov = x_mov/127.0+1;//ratio speed of the player from 1 (with 0 speed) to 2 (with 255 speed)
				x_mov *= 4.0;//base speed is 4m/s
				x_mov /= 20;//speed per tick, a tick is 50ms
				x_mov*=10;//multiply by 10 cause there are 10 case per meter
				int[] pos = player.getPosition();
				ArrayList<int[]> path = Global.bresenham(pos[0], pos[1], player.initialSpot.x, player.initialSpot.y);
				if((int)Math.round(x_mov)<path.size()){
					player.setPosition(path.get((int)Math.round(x_mov))[0], path.get((int)Math.round(x_mov))[1]);
				}
			}
			break;
			
		case RUN_TO_THE_BALL:
			int[] pos = player.getPosition();
			ArrayList<int[]> path = Global.bresenham(pos[0], pos[1], Global.ball.getPosition()[0], Global.ball.getPosition()[1]);
			if(path.size()>10){
				double x_mov = (double)player.speed;
				x_mov = x_mov/127.0+1;//ratio speed of the player from 1 (with 0 speed) to 2 (with 255 speed)
				x_mov *= 4.0;//base speed is 4m/s
				x_mov /= 20;//speed per tick, a tick is 50ms
				x_mov*=10;//multiply by 10 cause there are 10 case per meter
				player.setPosition(path.get((int)Math.round(x_mov))[0], path.get((int)Math.round(x_mov))[1]);
			}
			else{
				Random rand = new Random();
				int baseInterception = 0;
				double x_base = 0;
				if(player.ballState==2){
					System.out.println(player.isInLocalTeam+"\t"+player+"- je vais chercher une passe d'un coequipier");
					//if the player receive a pass, he has 98% base chance to get it
					baseInterception=98;
					x_base = 2.0;
				}
				else{
					System.out.println(player.isInLocalTeam+"\t"+player+"- je vais intercepter une passe");
					//else, the player only has 30% base chance to get it
					baseInterception=30;
					x_base = 15.0;
				}
				
				double x = Math.min(((double)Global.ball.velocity/127.0)*x_base,2*x_base);
				int interception = baseInterception + (int)x_base - (int)Math.round(x);
				int isIntercepted = rand.nextInt(100);
				boolean catchBall=false;
				if(isIntercepted<interception){
					catchBall=true;
				}
				//System.out.println(x+" - "+isIntercepted+"/"+interception+"- base : "+baseInterception);
				
				if(Global.getBallOwner()==null){
					if(catchBall){
						Player opponent = Global.nearestOpponent(player);
						ArrayList<int[]> dist_to_opp = Global.bresenham(pos[0], pos[1], opponent.getPosition()[0], opponent.getPosition()[1]);
						if(dist_to_opp.size()>10){
							Global.setBallOwner(player);
							player.ballState=0;
							player.refreshAction = 19;
						}
						else{
							if(this.dribble(opponent.dribble_level,player.dribble_level)){
								Global.setBallOwner(player);
								player.ballState=0;
								
								player.refreshAction=19;
								player.nextAction=Action.ATTACK;
								
								opponent.refreshAction=0;
								opponent.nextAction=Action.STAND;
							}
							else{
								Global.setBallOwner(opponent);
								player.ballState=0;

								player.refreshAction=0;
								player.nextAction=Action.STAND;
								
								opponent.refreshAction=19;
								opponent.nextAction=Action.ATTACK;
							}
						}
					}
					else{
						player.refreshAction = 0;
						player.nextAction = Action.STAND;
					}
				}
				else{
					if(Global.getBallOwner().isInLocalTeam==player.isInLocalTeam){
						player.nextAction=Action.ATTACK;
						player.refreshAction = 19;
					}
					else{
						if(dribble(Global.getBallOwner().dribble_level,player.dribble_level)){
							Global.setBallOwner(player);
							player.ballState=0;
							
							player.refreshAction=19;
							player.nextAction=Action.ATTACK;
							
							Global.getBallOwner().refreshAction=0;
							Global.getBallOwner().nextAction=Action.STAND;
						}
						else{
							player.ballState=0;
							
							player.refreshAction=0;
							player.nextAction=Action.STAND;
							
							Global.getBallOwner().refreshAction=19;
							Global.getBallOwner().nextAction=Action.ATTACK;
						}
					}
				}
			}
			break;
			
		default:
			break;
		}
	}
}
